import re
import sys

def read(file_name: str):
    '''
    读取一个mif文件。
    
    Parameters
    ----------
    file_name : str
        文件路径(.mif文件)。

    Returns
    -------
    out : str
        十六进制字符串数据。

    Notes
    -----
    仅支持解析以下参数的mif文件:
        ADDRESS_RADIX参数: 仅UNS；
        DATA_RADIX参数: 仅BIN。
    '''
    
    hex_list = list() # 存放数据
    with open(file_name, "r") as f: # 打开mif
        mif_data = f.read()
    
    width = int(re.search('WIDTH = \d+', mif_data, re.I).group()[8:]) # 获取宽度
    bin_list = re.compile(r'\d+').findall(mif_data) # 拿到数字列表
    for index in range(bin_list.index("0")+1, len(bin_list), 2):
        hex_list.append(int(bin_list[index],2).to_bytes(width//8, 'big').hex())
    return "".join(hex_list)

def write(file_name: str, data: str, *, data_radix: str, address_radix: str, width: int):
    '''
    生成一个mif文件。

    Parameters
    ----------
    file_name : str
        输出文件路径
    data : str
        不带0x前缀的十六进制字符串
    address_radix : str
        地址基数，当前仅支持'UNS'类型
    data_radix : str
        进制，当前仅支持'BIN'进制
    width : int
        数据宽度
    '''

    if address_radix != "UNS":
        print("only support UNS address radix.")
        sys.exit(0)
    if data_radix != "BIN":
        print("only support BIN data radix.")
        sys.exit(0)
    
    b_data = "" # 转二进制
    for index in range(0,len(data),2):
        byte_data = bin(int(data[index:index+2], 16))[2:]
        b_data += "0"*(8-len(byte_data))+byte_data
    patch_length = width-len(b_data)%width
    if patch_length != width: # 需要末尾补零
        b_data=b_data+"0"*patch_length

    with open(file_name, "w") as f:
        f.write("-- Copyright (C) 2021 Liao Haolong and all rights reserved.\n\n")
        f.write("-- Memory Initialization File (.mif) generated by every2coe can\n")
        f.write("-- be used in Quartus to initialize the roms or rams.\n\n")
        f.write("WIDTH = "+str(width)+";\n")
        depth = len(b_data)//width
        f.write("DEPTH = "+str(depth)+";\n\n")
        f.write("ADDRESS_RADIX = UNS;\n")
        f.write("DATA_RADIX = BIN;\n")
        f.write("CONTENT BEGIN\n")
        for i in range(0,depth):
            f.write("\t"+str(i)+"  :  "+b_data[i*width:(i+1)*width]+";\n")
        f.write("END;\n")